using System.Collections.Generic;
using Neatly.Tween;
using UnityEngine;
using UnityEngine.UI;

namespace Neatly.UI
{
    public class EffectImage : Image
    {
        #region 编辑配置
        ///1.Position
        [SerializeField]
        public bool positionEnable = false;
        [SerializeField]
        private Vector2 m_TargetPosition = Vector2.zero;
        public Vector2 TargetPosition => m_TargetPosition;
        [SerializeField]
        private float m_PosTimeTotal = 0;
        public float PosTimeTotal => m_PosTimeTotal;

        ///2.Rotation, use 
        [SerializeField]
        public bool rotateEnable = false;
        [SerializeField]
        private Vector3 m_TargetRotate = Vector3.zero;
        public Vector3 TargetRotate => m_TargetRotate;
        [SerializeField]
        private float m_RotateTimeTotal = 0;
        public float RotateTimeTotal => m_RotateTimeTotal;

        ///3.Color
        [SerializeField]
        public bool colorEnable = false;
        [SerializeField]
        private Color m_TargetColor = Color.white;
        public Color TargetColor => m_TargetColor;
        [SerializeField]
        private float m_ColorTimeTotal = 0;
        public float ColorTimeTotal => m_ColorTimeTotal;

        ///4.Scale
        [SerializeField]
        public bool scaleEnable = false;
        [SerializeField]
        private Vector3 m_TargetScale = Vector2.zero;
        public Vector2 TargetScale => m_TargetScale;
        [SerializeField]
        private float m_ScaleTimeTotal = 0;
        public float ScaleTimeTotal => m_ScaleTimeTotal;

        public bool useLoop = false;
        [SerializeField]
        private EffectLoopMode m_LoopMode = EffectLoopMode.None;

        private readonly List<EffectTweenImp> m_TweenImpList = new();
        #endregion

        protected override void Start()
        {
            raycastTarget = false;
            if (!Application.isPlaying) return;
            if (positionEnable)
            {
                var imp = EffectTween.Move(rectTransform, TargetPosition, PosTimeTotal).SetLoopMode(m_LoopMode);
                m_TweenImpList.Add(imp);
            }
            if (scaleEnable)
            {
                var imp = EffectTween.Scale(transform, TargetScale, ScaleTimeTotal).SetLoopMode(m_LoopMode);
                m_TweenImpList.Add(imp);
            }
            if (rotateEnable)
            {
                var imp = EffectTween.AutoRotate(transform, TargetRotate, RotateTimeTotal).SetLoopMode(m_LoopMode);
                m_TweenImpList.Add(imp);
            }
            if (colorEnable)
            {
                var imp = EffectTween.Color(this, TargetColor, ColorTimeTotal).SetLoopMode(m_LoopMode);
                m_TweenImpList.Add(imp);
            }
        }

        protected override void OnEnable()
        {
            base.OnEnable();
            for (int i = 0; i < m_TweenImpList.Count; i++)
            {
                m_TweenImpList[i].Resume();
            }
        }

        protected override void OnDisable()
        {
            base.OnDisable();
            foreach (var imp in m_TweenImpList)
            {
                imp.Pause();
            }
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();
            m_TweenImpList.Clear();
        }

        #region ParticleSystem Property
        private Vector2 m_ParDirect;
        private float m_ParLifeTime;
        private float m_ParTotalTime;
        private float m_ParSpeed;
        private bool m_EnableVelocity = false;
        private bool m_EnableForce = false;
        private bool m_EnableColor = false;
        private bool m_EnableSize = false;
        private bool m_EnableRotate = false;
        private Vector2 m_Velocity;
        private Vector2 m_Force;
        private Color m_StartColor;
        private Color m_FinalColor;
        private Vector2 m_StartSize;
        private Vector2 m_FinalSize;

        private Vector2 ParDistance
        {
            get
            {
                Vector2 dis = m_ParDirect;
                if (m_EnableVelocity)
                {
                    dis += m_Velocity;
                }
                if (m_EnableForce)
                {
                    dis += m_Force * m_ParTotalTime;
                }
                return dis;
            }
        }
        #endregion

        #region ParticleSystem Function

        /// <summary>
        /// Set start info
        /// </summary>
        /// <param name="position"></param>
        /// <param name="size"></param>
        /// <param name="lifeTime"></param>
        /// <param name="direct"></param>
        /// <param name="speed"></param>
        public void SetStartInfo(Vector2 position, Vector2 size, float lifeTime, Vector2 direct, float speed)
        {
            rectTransform.anchoredPosition = position;
            rectTransform.sizeDelta = size;
            rectTransform.localScale = Vector2.one;
            m_ParLifeTime = lifeTime;
            m_ParDirect = direct;
            m_ParTotalTime = 0;
            m_ParSpeed = speed;
            m_EnableVelocity = false;
            m_EnableForce = false;
            m_EnableColor = false;
            m_EnableSize = false;
            m_EnableRotate = false;
        }

        /// <summary>
        /// Set sprite and material
        /// </summary>
        /// <param name="sp"></param>
        /// <param name="mat"></param>
        /// <param name="col"></param>
        public void SetSpriteInfo(Sprite sp, Material mat, Color col)
        {
            if (sprite != sp)
            {
                sprite = sp;
            }
            if (mat && material != mat)
            {
                material = mat;
            }
            color = col;
        }

        /// <summary>
        /// Add Velocity
        /// </summary>
        /// <param name="velocity"></param>
        public void AddVelocity(Vector2 velocity)
        {
            m_Velocity = velocity;
            m_EnableVelocity = true;
        }

        /// <summary>
        /// Add Force
        /// </summary>
        /// <param name="force"></param>
        public void AddForce(Vector2 force)
        {
            m_Force = force;
            m_EnableForce = true;
        }

        /// <summary>
        /// Enable Color Tween
        /// </summary>
        /// <param name="finalColor"></param>
        public void AddColorTween(Color finalColor)
        {
            m_StartColor = color;
            m_FinalColor = finalColor;
            m_EnableColor = true;
        }

        /// <summary>
        /// Add Size Tween
        /// </summary>
        /// <param name="finalSize"></param>
        public void AddSizeTween(Vector2 finalSize)
        {
            m_StartSize = rectTransform.sizeDelta;
            m_FinalSize = finalSize;
            m_EnableSize = true;
        }

        /// <summary>
        /// particle update(if finish job, then return true, else false,)
        /// </summary>
        /// <param name="deltaTime"></param>
        /// <returns></returns>
        public bool ParticleUpdate(float deltaTime)
        {
            m_ParTotalTime += deltaTime;
            if (m_ParTotalTime > m_ParLifeTime) return true;
            //Todo: Do job 执行方向 动画
            ExcutePosition(deltaTime);
            ExcuteTween();
            return false;
        }

        private void ExcutePosition(float deltaTime)
        {
            rectTransform.anchoredPosition += ParDistance * deltaTime * m_ParSpeed;
        }
        private void ExcuteTween()
        {
            float t = m_ParTotalTime / m_ParLifeTime;
            if (m_EnableColor)
            {
                color = Color.Lerp(m_StartColor, m_FinalColor, t);
            }
            if (m_EnableSize)
            {
                rectTransform.sizeDelta = Vector2.Lerp(m_StartSize, m_FinalSize, t);
            }
        }

        public void Finish()
        {
            rectTransform.localScale = Vector3.zero;
        }

        public void Hide()
        {
            transform.localScale = Vector3.zero;
        }

        public void Show()
        {
            transform.localScale = Vector3.one;
        }

        /// <summary>
        /// Clear all tween and sprite data
        /// </summary>
        public void Clear()
        {
            positionEnable = false;
            scaleEnable = false;
            rotateEnable = false;
            colorEnable = false;
            sprite = null;
            material = null;
            EffectTween.Cancel(gameObject);
        }
        #endregion

    }
}
